计算机原理学习(3)

您所在的位置:网站首页 计算机系统组成 结构图 计算机原理学习(3)

计算机原理学习(3)

2023-12-24 18:21| 来源: 网络整理| 查看: 265

前言

 

前面两篇文章介绍了计算机硬件是如何工作的。而从这一章开始将逐渐的转到软件上面来。我们还有内存这一个很重要的部分没有介绍。这一章不仅仅介绍内存的工作原理,还会介绍内存的编址、内存数据存放。逐渐从硬件过渡到软件上来。为后面介绍程序运行打下基础。

 

1. 内存工作原理

 

CPU和内存是计算机中最重要的两个组件,前面已经知道了CPU是如何工作的,上一篇也介绍了内存采用的DRAM的存储原理。CPU工作需要知道指令或数据的内存地址,那么这样一个地址是如何和内存这样一个硬件联系起来的呢?现在就看看内存到的是怎么工作的。

 

1.1 DRAM芯片结构

上图是DRAM芯片一个单元的结构图。一个单元被分为了N个超单元(可以叫做cell),每个单元由M个DRAM单元组成。我们知道一个DRAM单元可以存放1bit数据, 所以描述一个DRAM芯片可以存储N*M位数据。上图就是一个有16个超单元,每个单元8位的存储模块,我们可以称为16*8bit 的DRAM芯片。而超单元(2,1)我们可以通过如矩阵的方式访问,比如 data = DRAM[2.1] 。这样每个超单元都能有唯一的地址,这也是内存地址的基础。

 

每个超单元的信息通过地址线和数据线传输查找和传输数据。如上图有2根地址线和8根数据线连接到存储控制器(注意这里的存储控制器和前面讲的北桥的内存控制器不是一回事),存储控制器电路一次可以传送M位数据到DRAM芯片或从DRAM传出M位数据。为了读取或写入【i,j】超单元的数据,存储控制器需要通过地址线传入行地址i 和列地址j。这里我们把行地址称为RAS(Row Access Strobe)请求, 列地址称为(Column Access Strobe)请求。

但是我们发现地址线只有2为,也就是寻址空间是0-3。而确定一个超单元至少需要4位地址线,那么是怎么实现的呢?

解决这个问题采用的是分时传送地址码的方法。看上图我们可以发现在DRAM芯片内部有一个行缓冲区,实际上获取一个cell的数据,是传送了2次数据,第一次发送RAS,将一行的数据放入行缓冲区,第二期发送CAS,从行缓冲区中取得数据并通过数据线传出。这些地址线和数据线在芯片上是以管脚(PIN)与控制电路相连的。将DRAM电路设计成二维矩阵而不是一位线性数组是为了降低芯片上的管脚数量。入上图如果使用线性数组,需要4根地址管脚,而采用二维矩阵并使用RAS\CAS两次请求的方式只需要2个地址管脚。但这样的缺点是增加了访问时间。

 

 

1.2 内存模块

 

内存模块也就是我们常说的内存条。我们在购买内存是经常会听到我这个内存采用的是什么颗粒,如下左图,我们看到内存PCB上的一块块的就是内存颗粒。也就是我们DRAM芯片。通过管脚和PCB连接。不同厂商,不同类型的内存可以的大小,管脚,性能,封装都不一样,但是原理都是一样。这里我们就不展开介绍了。而下有图展示了一个1M*4bit的DRAM芯片的管脚图。

 

对于一个内存颗粒来说,它的容量和字长是有限的,所以我们使用内存是会把多个颗粒组成内存模块来对内存进行字长和容量的扩展。目前的内存一般内存条上面会有多颗内存颗粒,比如一条64M的内存可能是由8个8M*8bit 的SDRAM内存颗粒组成。

 

1.2.1 字长位数扩展 

位扩展的方法很简单,只需将多片RAM的相应地址端、读/写控制端 和片选信号CS并接在一起,而各片RAM的I/O端并行输出即可。 如上图,我们采用了8个DRAM芯片分,别编号为0-7,每个超单元中存储8位数据。在获取add(row=i,col=j)地址的数据的时候,从每个DRAM芯片的【i, j】单元取出一个字节的数据,这样传送到CPU的一共是8*8b = 64b的数据。我们通过8个8M*8b的内存颗粒扩展为了8M*64b的内存模块。

 

 

1.2.2 字存储容量扩展

 

RAM的字扩展是利用译码器输出控制各片RAM的片选信号CS来实现的。RAM进行字扩展时必须增加地址线,而增加的地址线作为高位地址与译码器的输入相连。同时各片RAM的相应地址端、读/写控制端 、相应I/O端应并接在一起使用。下图是我们通过4个2M*8b的内存颗粒,将内存容量扩展到了8M,字长为8位。

 

最后,内存通过主板上的内存插槽DIMM和内存总线相连接。对于不同内存比如SDRAM和DDR他们内存金手指的定义是不同的。这里就不需要详细介绍了。

 

2. 内存编址

 

前面我们知道了DRAM颗粒以及内存模块是如何扩展字长和容量的。一个内存可能是8位,也可能是64位,容量可能是1M,也可能是1G。那么内存是如何编地的呢?和地址总线,计算机字长之间又有什么关系呢?

 

 

2.1 字长

 

计算机在同一时间内处理的一组二进制数称为一个计算机的“字”,而这组二进制数的位数就是“字长”。。通常称处理字长为8位数据的CPU叫8位CPU,32位CPU就是在同一时间内处理字长为32位的二进制数据。 所以这里的字并不是我们理解的双字节(Word)而是和硬件相关的一个概念。一般来说计算机的数据线的位数和字长是相同的。这样从内存获取数据后,只需要一次就能把数据全部传送给CPU。

 

2.2 地址总线

 

前面我们已经介绍过地址总线的功能。地址总线的数量决定了他最大的寻址范围。就目前来说一般地址总线先字长相同。比如32位计算机拥有32为数据线和32为地线,最大寻址范围是4G(0x00000000 ~ 0xFFFFFFFF)。当然也有例外,Intel的8086是16为字长的CPU,采用了16位数据线和20位数据线。

 

2.3 内存编址

 

从前面我们知道一个内存的大小和它芯片扩展方式有关。比如我们内存模块是采用 16M*8bit的内存颗粒,那么我们使用4个颗粒进行位扩展,成为16M*32bit,使用4个颗粒进行字容量扩展变为64M*32bit。那么我们内存模块使用了16个内存颗粒,实际大小是256MB。

 

我们需要对这个256M的内存进行编址以便CPU能够使用它,通常我们多种编址方式:

按字编址:    对于这个256M内存来说,它的寻址范围是64M,而每个内存地址可以存储32bit数据。按半字编址:对于这个256M内存来说,它的寻址范围是128M,而每个内存地址可以存储16bit数据。按字节编址:对于这个256M内存来说,它的寻址范围是256M,而每个内存地址可以存储8bit数据。

对于我们现在的计算机来说,主要都是采用按字节编址的方式。所以我们可以把内存简单的看成一个线性数组,数组每个元素的大小为8bit,我们称为一个存储单元。这一点很重要,因为后面讨论的所有问题内存都是以按字节编址的方式。 这也是为什么对于32位计算机来说,能使用的最多容量的内存为4GB。如果我们按字编地址,能使用的最大内存容量就是16GB了。

 

于是很容易想到一个问题,为什么我们要采用字节编址的方式呢?关于这个问题,我在网上基本没有找到答案,甚至都找不到问这个问题的。所以这里没法给出答案,为什么为什么呢? 麻烦知道的朋友告诉我哈。

 

另一方面的问题是,内存编址方式和DRAM芯片是否有关呢? 我认为还是有一定关系。比如我DRAM的芯片是8M*8bit,那么芯片最小的存储单位就是8bit,那么我们内存编址就不能按照半个字节来编址。否则内存取出8bit,根本不知道你要那4bit传给CPU。也有一种说法是现在的DRAM芯片cell都是8bit,所以采用按字节编址。另一方面应该也和数据总线位宽有关。

 

 

3. 内存数据

 

前面我们知道了,内存是按字节编址,每个地址的存储单元可以存放8bit的数据。我们也知道CPU通过内存地址获取一条指令和数据,而他们存在存储单元中。现在就有一个问题。我们的数据和指令不可能刚好是8bit,如果小于8位,没什么问题,顶多是浪费几位(或许按字节编址是为了节省内存空间考虑)。但是当数据或指令的长度大于8bit呢?因为这种情况是很容易出现的,比如一个16bit的Int数据在内存是如何存储的呢?

 

3.1 内存数据存放

 

其实一个简单的办法就是使用多个存储单元来存放数据或指令。比如Int16使用2个内存单元,而Int32使用4个内存单元。当读取数据时,一次读取多个内存单元。于是这里又出现2个问题:

多个存储单元存储的顺序?如何确定要读几个内存单元?

 

3.1.1 大端和小端存储 Little-Endian 就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。Big-Endian 就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

需要说明的是,计算机采用大端还是小端存储是CPU来决定的, 我们常用的X86体系的CPU采用小端,一下ARM体系的CPU也是用小端,但有一些CPU却采用大端比如PowerPC、Sun。判断CPU采用哪种方式很简单:

bool IsBigEndian() { int vlaue = 0x1234; char lowAdd = *(char *)&value; if( lowAdd == 0x12) { return true; } return false; }

既然不同计算机存储的方式不同,那么在不同计算机之间交互就可能需要进行大小端的转换。这一点我们在Socket编程中可以看到。这里就不介绍了,对以我们单一CPU来说我们可以不需要管这个转换的问题,另外我们目前个人PC都是采用小端方式,所以我们后面默认都是这种方式。

 

3.1.2 CPU指令

前面我们多次提到了指令的概念,也知道指令是0和1组成的,而汇编代码提高了机器码的可读性。为什么突然在这里介绍CPU指令呢? 主要是解释上面的第二个问题,当我读取一个数据或指令时,我怎么知道需要读取多少个内存单元。

 

3.1.2.1 CPU指令格式

首先我们来看看CPU指令的格式,我们知道CPU质量主要就是告诉CPU做什么事情,所以一条CPU指令一般包含操作码(OP)和操作

  操作码字段   地址码字段

 

 

根据一条指令中有几个操作数地址,可将该指令称为几操作数指令或几地址指令。

 操作码 A1 A2 A3

 

三地址指令: (A1) OP (A2) --> A3

 操作码 A1 A2

 

二地址指令: (A1) OP (A2) --> A1

 操作码  A1

 

一地址指令: (AC) OP (A) --> AC   

 操作码 

 

    零地址指令

A1为被操作数地址,也称源操作数地址; A2为操作数地址,也称终点操作数地址; A3为存放结果的地址。 同样,A1,A2,A3以是内存中的单元地址,也可以是运算器中通用寄存器的地址。所以就有一个寻址的问题。关于指令寻址后面会介绍。

CPU指令设计是十分复杂的,因为在计算机中都是0和1保存,那计算机如何区分一条指令中的操作数和操作码呢?如何保证指令不会重复呢?这个不是我们讨论的重点,有兴趣的可以看看计算机体系结构的书,里面都会有介绍。从上图来看我们知道CPU的指令长度是变长的。所以CPU并不能确定一条指令需要占用几个内存单元,那么CPU又是如何确定一条指令是否读取完了呢?

 

3.1.2.2 指令的获取

现在的CPU多数采用可变长指令系统。关键是指令的第一字节。 当CPU读指令时,并不是一下把整个指令读近来,而是先读入指令的第一个字节。指令译码器分析这个字节,就知道这是几字节指令。接着顺序读入后面的字节。每读一个字节,程序计数器PC加一。整个指令读入后,PC就指向下一指令(等于为读下一指令做好了准备)。

Sample1:

MOV AL,00 机器码是1011 0000 0000 0000

机器码是16位在内存中占用2个字节:

【00000000】



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3